﻿using RedisHelp;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace StackExchange.Redis_Demo
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            RedisHelper redis = new RedisHelper(0);

            #region String

            string str = "123";
            Demo demo = new Demo()
            {
                Id = 1,
                Name = "123"
            };
            var resukt = redis.StringSet("redis_string_test", str);
            var str1 = redis.StringGet("redis_string_test");
            redis.StringSet("redis_string_model", demo);
            var model = redis.StringGet<Demo>("redis_string_model");

            for (int i = 0; i < 10; i++)
            {
                redis.StringIncrement("StringIncrement", 2);
            }
            for (int i = 0; i < 10; i++)
            {
                redis.StringDecrement("StringIncrement");
            }
            redis.StringSet("redis_string_model1", demo, TimeSpan.FromSeconds(10));

            #endregion String

            #region List

            for (int i = 0; i < 10; i++)
            {
                redis.ListRightPush("list", i);
            }

            for (int i = 10; i < 20; i++)
            {
                redis.ListLeftPush("list", i);
            }
            var length = redis.ListLength("list");

            var leftpop = redis.ListLeftPop<string>("list");
            var rightPop = redis.ListRightPop<string>("list");

            var list = redis.ListRange<int>("list");

            #endregion List

            #region Hash

            redis.HashSet("user", "u1", "123");
            redis.HashSet("user", "u2", "1234");
            redis.HashSet("user", "u3", "1235");
            var news = redis.HashGet<string>("user", "u2");

            #endregion Hash

            #region 发布订阅

            redis.Subscribe("Channel1");
            for (int i = 0; i < 10; i++)
            {
                redis.Publish("Channel1", "msg" + i);
                if (i == 2)
                {
                  //  redis.Unsubscribe("Channel1");
                }
            }

            #endregion 发布订阅

            #region 事务

            var tran = redis.CreateTransaction();

            tran.StringSetAsync("tran_string", "test1");
            tran.StringSetAsync("tran_string1", "test2");
            bool committed = tran.Execute();

            #endregion 事务

            #region Lock

            //var db = redis.GetDatabase();
            //RedisValue token = Environment.MachineName;
            //if (db.LockTake("lock_test", token, TimeSpan.FromSeconds(10)))
            //{
            //    try
            //    {
            //        //TODO:开始做你需要的事情
            //        Thread.Sleep(5000);
            //    }
            //    finally
            //    {
            //        db.LockRelease("lock_test", token);
            //    }
            //}
            Test_SetValue(redis);
            Test_GetValue_Tasks(redis);
            #endregion Lock
            System.Console.ReadKey();
            #region 发布订阅

            for (int i = 0; i < 10; i++)
            {
                redis.Publish("Channel1", " 333 msg" + i);
                if (i == 2)
                {
                    //  redis.Unsubscribe("Channel1");
                }
            }
            Test_GetValue_Tasks(redis);
            #endregion 发布订阅
            System.Console.ReadKey();
        }
        static void Test_SetValue(RedisHelper redis)
        {
            List<Person> people = new List<Person>()
            {
                new Person(1, "Joe", new List<Contact>()
                {
                    new Contact("1", "123456789"),
                    new Contact("2", "234567890")
                }),
                new Person(2, "Joe2", new List<Contact>()
                {
                    new Contact("12", "1234567289"),
                    new Contact("22", "2345672890")
                })
            };
            redis.HashSet("user", "People", people);
            ////批量写
            //var batch = redis.GetDatabase().CreateBatch();
            ////Task t1 = batch.StringSetAsync("name", "羽");
            ////Task t2 = batch.StringSetAsync("age", 22);
            //var Tasks = new List<Task>();
            //for (int i = 0; i < 10000; i++)
            //{
            //    //redis.ListRightPush("Peoplelist", people);
            //    Tasks.Add(batch.ListRightPushAsync("Peoplelist", redis.ConvertJson(people)));
            //}
            //batch.Execute();
            ////Task.WaitAll(Tasks.ToArray());
            redis.StringSet("People", people);
        }
        static void Test_GetValue_Tasks(RedisHelper redis)
        {
            const int noOfClients = 10000;
            var tasks = new Task[noOfClients];
            var c = 0;
            var ie = 0;
            var watch1 = new Stopwatch();
            //开始计时
            watch1.Start();
            for (var i = 0; i < noOfClients; i++)
            {
                Thread.Sleep(10);
                tasks[i] = Task.Factory.StartNew((object clientNo) =>
                {
                    try
                    {
                        var db = redis.GetDatabase();
                        RedisValue token = Environment.MachineName;
                        // if (db.LockTake("lock_test", token, TimeSpan.FromSeconds(10)))
                        using (new RedisLock(db, "lock_test", TimeSpan.FromSeconds(20)))
                        {
                            //try
                            //{
                            //TODO:开始做你需要的事情
                            //Thread.Sleep(5000);
                            var watch = new Stopwatch();
                            //开始计时
                            watch.Start();
                            if (!redis.KeyExists("atomic-counter")) redis.StringSet("atomic-counter", 0);
                            var counter = redis.StringGet<int>("atomic-counter");
                            var contacts = redis.StringGet<List<Person>>("People");
                            var pl = redis.HashGet<List<Person>>("user", "People");
                            var contactslist =redis.ListRange<List<Person>>("Peoplelist");
                            //Thread.Sleep(10);
                            redis.StringSet("atomic-counter", counter + 1);
                            watch.Stop();
                            Console.WriteLine("client {0} released lock,contactslist.Count={1},watch.ElapsedMilliseconds={2},atomic-counter={3}", (int)clientNo, contactslist.Count, watch.ElapsedMilliseconds, counter);
                            //}
                            //finally
                            //{
                            //    db.LockRelease("lock_test", token);
                            //}
                        }
                    }
                    catch (Exception e)
                    {
                        ie++;
                        Console.WriteLine("client {0} " + e.Message, (int)clientNo);
                    }
                    c++;
                    if (noOfClients <= c)
                    {
                        watch1.Stop();
                        Console.WriteLine("client c={0},ie={1},ElapsedMilliseconds={2} ", c, ie, watch1.ElapsedMilliseconds);
                    }
                }, i + 1);
            }
        }
    }

    public class Demo
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Contact
    {
        public string Type { get; set; }

        public string Value { get; set; }

        public Contact(string type, string value)
        {
            this.Type = type;
            this.Value = value;
        }
    }

    public class Person
    {
        public long Id { get; set; }

        public int Age { get; set; }
        public string Name { get; set; }

        public List<Contact> Contacts { get; set; }

        public Person(long id, string name, List<Contact> contacts)
        {
            this.Id = id;
            this.Name = name;
            this.Contacts = contacts;
        }
    }
}